在寫程式的過程中,我們經常會遇到一個類別或模組負責太多事情,結果導致程式碼難以維護或修改,這種情況常常被稱為「巨石類別 (God Class)」。當我們需要對程式碼做出任何變更時,這種「巨石類別」會變得相當脆弱,因為它的每一個改動都有可能對其他功能造成影響。這時候,「單一職責原則 (Single Responsibility Principle, SRP)」便能幫助我們解決這個問題。
簡單來說,單一職責原則強調每個類別或模組應該只負責一件事,也就是說每個類別應該只專注於它的核心功能。如果一個類別有多於一個原因會導致它需要變更,那麼這個類別就違反了單一職責原則。
用白話來說,就是「一個人做好一件事」的概念。在軟體設計中,我們應該避免讓一個類別承擔太多不同的責任,這樣不僅會讓程式碼更具彈性,也更容易進行維護。
讓我們來看一個簡單的例子,理解什麼樣的設計違反了單一職責原則。
我們可以先從一個不遵守單一職責原則的範例來看。假設你有一個「報告管理」類別,這個類別同時負責產生報告內容和報告的儲存:
class ReportManager {
public:
void generateReport() {
// 產生報告的邏輯
}
void saveToFile(const std::string& filename) {
// 將報告儲存至檔案
}
};
這個 ReportManager
類別明顯負責了兩件事:一是產生報告,二是將報告儲存至檔案。這樣的設計違反了單一職責原則,因為當你需要修改報告產生邏輯時,可能會影響到報告儲存的邏輯,反之亦然。
這種違反單一職責原則的設計會使程式碼變得難以維護。隨著功能增多,我們可能會發現 ReportManager
會變得越來越臃腫,最終變成「巨石類別」,任何改動都會影響整個類別的穩定性。
那麼要如何設計一個符合單一職責原則的解決方案呢?我們可以將 ReportManager
的責任拆分成兩個類別,一個專注於報告產生,另一個專注於報告儲存:
class ReportGenerator {
public:
void generateReport() {
// 產生報告的邏輯
}
};
class ReportSaver {
public:
void saveToFile(const std::string& filename) {
// 將報告儲存至檔案的邏輯
}
};
現在我們的 ReportGenerator
類別只專注於報告產生,而 ReportSaver
類別則負責儲存報告。這樣的設計遵守了單一職責原則,因為每個類別只負責一件事。當我們需要修改報告產生的邏輯時,並不會影響到報告儲存的功能,反之亦然。
單一職責原則的最大好處在於降低類別之間的耦合度。當每個類別都只負責一件事時,程式碼變更時不會影響到其他不相關的部分,這樣能夠有效降低系統的出錯機率。這也讓我們的程式碼更具可測試性,因為每個類別都只有單一的責任,單元測試時只需要關注這個類別的核心功能即可。
此外,單一職責原則還提升了系統的可維護性。隨著需求的變更,我們能夠更加輕鬆地對系統進行修改,因為我們不必擔心一個類別承擔了太多的責任,導致改動影響整個系統的穩定性。
當然,過度拆分職責可能會導致過度設計,特別是在小型專案中,每個功能都被分得太細反而會增加程式碼的複雜性。因此遵守單一職責原則時,需要根據實際需求找到平衡。
單一職責原則在實際開發中應用廣泛,尤其是在大型專案或持續演進的系統中尤為重要。無論是類別設計還是模組拆分,遵守單一職責原則能夠有效提升系統的可擴展性與可維護性。
例如,在設計軟體框架時,我們會將不同功能的模組分開,確保每個模組只負責單一職責,這樣開發者在擴展功能時,可以很輕鬆地新增或修改特定模組,而不必擔心破壞其他模組的運作。
更多C++語言相關的文章,歡迎追蹤我的部落格
https://shengyu7697.github.io/single-responsibility-principle/